package com.qwiki.dict;

import java.io.File;
import java.io.LineNumberReader;
import java.nio.charset.Charset;
import java.nio.file.Files;

import com.qwiki.content.AdhocCategoryFilter;
import com.qwiki.content.StringFilter;

import org.apache.log4j.ConsoleAppender;
import org.apache.log4j.Logger;
import org.apache.log4j.PatternLayout;

import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;

public class CategoryDictionary implements Dictionary {
  private static final Logger _log = Logger.getLogger(CategoryDictionary.class);

  private final String filename;
  private final StringFilter filter;
  private final int lowfreq, highfreq;
  private final Object2IntOpenHashMap<String> freqMap = new Object2IntOpenHashMap<String>();

  public CategoryDictionary(String filename) {
    this(filename, 0, Integer.MAX_VALUE);
  }

  public CategoryDictionary(String filename, int lowFreq) {
    this(filename, lowFreq, Integer.MAX_VALUE);
  }

  public CategoryDictionary(String filename, int lowFreq, int highFreq) {
    this.filename = filename;
    filter = new AdhocCategoryFilter();
    lowfreq = lowFreq;
    highfreq = highFreq;
    load();
  }

  private void load() {
    File file = new File(filename);
    LineNumberReader reader = null;
    try {
      reader = new LineNumberReader(Files.newBufferedReader(file.toPath(), Charset.forName("UTF-8")));
      String line = null;
      line = reader.readLine();
      int totalNumberOfWords = 0;
      int numberOfWords = 0;
      while (line != null) {
        int colon = line.indexOf(':');
        if (colon > 0) {
          totalNumberOfWords++;
          int count = Integer.parseInt(line.substring(0, colon).trim());
          String word = line.substring(colon + 1).trim().toLowerCase();
          if (filter.isGood(word) && count >= lowfreq && count <= highfreq) {
            numberOfWords++;
            if (freqMap.containsKey(word)) {
              _log.warn("duplicating word: " + word + " in dictionary " + filename + " old count: " + freqMap.getInt(word) + " new count: " + count);
              count += freqMap.getInt(word); // tally the total count under duplicates
            }
            freqMap.put(word, count);
            System.out.println(word + " : " + count);
          }
        }
        line = reader.readLine();
      }
      _log.info("dictionary " + filename + " loaded " + numberOfWords + " from " + totalNumberOfWords);
    } catch (Exception e) {
      _log.error("failed to load dictionary " + filename, e);
    }
  }


  @Override
  public boolean contains(String string) {
    return freqMap.containsKey(string.trim().toLowerCase());
  }

  @Override
  public String[] filter(String[] raw) {
    for (int i = 0; i < raw.length; i++) {
      if (!contains(raw[i])) raw[i] = "";
    }
    return raw;
  }

  @Override
  public String filter(String string) {
    String[] split = string.split(" ");
    split = filter(split);
    StringBuilder sb = new StringBuilder();
    for (String token : split) {
      sb.append(token).append(" ");
    }
    return sb.toString();
  }

  public static final CategoryDictionary dict = new CategoryDictionary("/Users/xgu/opensrc/qwiki/categoryRaw.dict", 10);

  public static void main(String args[]) {
    Logger.getRootLogger()
        .addAppender(new ConsoleAppender(new PatternLayout("%d{yyyy/MM/dd HH:mm:ss.SSS} %p [%c{1}] [%x] %m%n")));
    CategoryDictionary dict = new CategoryDictionary("/Users/xgu/opensrc/qwiki/categoryRaw.dict", 10);

  }
}
